package com.doophan.dac.client.socket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * Socket Client
 * @author Vincent Wu
 * @date 2021-04-01
 */
@Component
@Slf4j
public class SocketClientRunner implements CommandLineRunner {

    private static List<Socket> clients;

    private static final int SOCKET_NUM = 200;

    @Resource
    private RestTemplate restTemplate;

    private static void init() {
        boolean loop = true;
        while(loop) {
            try {
                initSockets();
                loop = false;
                log.info("==================socket连接成功=================");
            } catch (Exception e) {
                loop = true;
                log.info("==================socket连接失败,1s后重试=================");
            }
        }
    }

    private static void initSockets() throws IOException {
        clients = new CopyOnWriteArrayList<>();
        for (int i = 0; i < SOCKET_NUM; i++) {
//            Socket socket = new Socket("116.85.26.151", 9999);
            Socket socket = new Socket("localhost", 9999);
            // 0-空闲 1-忙碌
            clients.add(socket);
        }
        log.info("==============成功创建"+SOCKET_NUM+"个socket连接==============");
    }

    @Override
    public void run(String... args) throws Exception {
        init();
        ExecutorService threadPool = Executors.newCachedThreadPool();
        boolean loop = true;
        while(loop) {
            loop = false;
            List<Future<Integer>> ress = new ArrayList<>();
            for (Socket client : clients) {
                SocketThread thread = new SocketThread(client, restTemplate);
                Future<Integer> res = threadPool.submit(thread);
                ress.add(res);
            }
            for(Future<Integer> res : ress) {
                // 线程异常退出,重建连接
                if(res.get() == -1) {
                    loop = true;
                    init();
                    break;
                }
            }
        }
    }
}